<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>语法</title>
</head>

<body>
  <script>
    // 使用严格模式
    "use strict"
    function doSomething() {
      // 在函数内部使用严格模式.
      "use strict"
      //function body
    }
    // 还是建议加上分号.
    // let sum = a + b
    // let diff = a - b;

    // 只有一条执行语句,省略代码块
    if (test) console.log(test);
    //最佳实践,始终在控制语句中使用代码块
    if (test1) { console.log(test1) };
    //var,不初始化的情况下,值为underfined.
    var message;
    var msg = "hi";
    // 合法,但不推荐,在严格模式下会报错
    // num = 10;

    function test() {
      var msg2 = "hhh"
    }
    test()
    // console.log(msg2)  报错!

    function test1() {
      // msg3 = "Hello"  ,严格模式下会报错,创建的是全局变量.
    }
    test1()
    // console.log(msg3)

    //var声明提升
    function foo() {
      console.log(age);
      var age = 26;
    }
    foo()  //underfined

    // 上面的函数等价于:
    function foo1() {
      var age;
      console.log(age);
      age = 26;
    }
    foo1() // underfined

    // 反复声明同一个变量
    function foo2() {
      var age = 12;
      var age = 13;
      var age = 22;
      var age = 24;
      console.log(age)
    }
    foo2()
    // var是函数作用域
    if (true) {
      var name = "Sloan"
      console.log(name) //Sloan
    }
    console.log(name) //Sloan
    // let是块级作用域,仅限于该if块内部.
    if (true) {
      let age = 33;
      console.log(age)
    }
    // console.log(age)    age is not defined
    // let age;
    // let age;  SyntaxError,标识符age已经被声明过了.

    // 同一个块中没有重复声明.
    let age1 = 30;
    console.log(age1); //30
    if (true) {
      let age1 = 26;
      console.log(age1); //26
    }
    // var a;
    // let a; 报错,a已经被定义过了.

    // console.log(b);  报错,let声明不会被提升.
    let b = 22;
    console.log(window.b) //underfined,let声明不会成为window的属性.
    var c = 44;
    console.log(window.c) // 44

    // 条件声明
    let name0 = "Sloan Li";
    let age0 = 18;
    if (typeof name0 === 'underfined') {
      let name0;
    }
    // name0被限制在if块内,相当于全局赋值.
    name0 = "hhh"

    try {
      // console.log(age); 报错,age被限制在catch块内,把let换成var会是underfined.
    } catch (error) {
      let age;
    }
    // 形同全局赋值.
    // age = 27;

    //for循环中的let声明.
    for (var i = 0; i < 5; ++i) {
      setTimeout(() => console.log(i), 0) // 5 5 5 5 5
    }
    // console.log(i)   //5
    for (let j = 0; j < 5; ++j) {
      setTimeout(() => console.log(j), 0) // 0 1 2 3 4
    }
    // console.log(j)  j is not defined.

    //const声明
    const age2 = 33;
    // age2 = 44; 报错,无法修改age2的值.

    const name1 = "Matt";
    if (true) { const name1 = "Noodn"; } //const也是块级作用域.
    console.log(name1); // Matt

    const person = {
      name:"LiShilong"
    }
    person.name = "Sloan Li"
    console.log(person) // name:"Sloan Li".
    // const 可以创建不会被修改的循环变量.
    for(const key in {a:1,b:2}){
      console.log(key)  //a,b
    }

    for(const value of [1,2,3,4,5]){
      console.log(value)  // 1,2,3,4,5
    }

  </script>
</body>

</html>